<template>
  <a-select
    style="width: 100%"
    :disabled="disabled"
    :placeholder="placeholder"
    v-bind="uiAttr"
    :mode="multiple ? 'multiple' : ''"
    :filterOption="dict ? false : filterOption"
    v-model="modelValue"
    @search="handleSearch"
    @change="handleChange"
    :notFoundContent="loading ? undefined : null"
  >
    <a-spin v-if="loading" slot="notFoundContent" size="small" />
    <a-select-option v-for="item in options" :key="item.value" :value="item.value" :title="item.text">{{
      item.text
    }}</a-select-option>
  </a-select>
</template>

<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
import { getAction } from '../../api/manage'
import { simpleDebounce } from '@/utils/util'

/**
 * 注意：
 * dictOptions,dictCode,dict这三个参数只能传一个，否则功能会冲突
 */
export default {
  name: 'JSearchSelectTagNew',
  props: {
    value: String, //支持v-model，未选中时向外传递undefined,如果是多选，接收和传递的是一个逗号分割的字符串
    //选项集合
    dictOptions: {
      type: Array,
      default: () => [],
    },
    //字典查询字段
    dictCode: {
      type: String,
      default: '',
    },
    //查数据库表的检索条件
    dict: {
      type: String,
      default: '',
    },
    // 远程检索的分页大小，dict有配置时，才有意义
    pageSize: {
      type: Number,
      default: 10,
    },
    // 是否支持多选
    multiple: {
      type: Boolean,
      default: false,
    },
    // 内容提示
    placeholder: {
      type: String,
      default: '请选择',
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    // 下拉原则器原生配置项会与默认当前组件uiAttr默认配置进行合并,ui效果，禁用效果等 https://www.antdv.com/components/select-cn
    uiProps: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      loading: false,
      modelValue: undefined,
      options: [], // 下拉列表
      selectedOptions: [],
      uiAttr: {
        showSearch: true,
        allowClear: true,
      },
    }
  },
  created() {
    this.loadOptions(this.value)
  },
  watch: {
    dictOptions: {
      immediate: true,
      handler(val) {
        if (val && val.length > 0) {
          this.options = JSON.parse(JSON.stringify(val))
        }
      },
    },
    value: {
      immediate: true,
      handler(val) {
        if (this.multiple) {
          this.modelValue = val ? val.split(',') : []
        } else {
          this.modelValue = val ? val : undefined //处理值为空字符串时placeholder不显示问题
        }
      },
    },
    uiProps: {
      immediate: true,
      deep: true,
      handler(val) {
        this.uiAttr = { ...this.uiAttr, ...val }
      },
    },
  },
  methods: {
    //  加载字典数据
    loadOptions(value) {
      if (!this.dictOptions.length) {
        if (this.dictCode) {
          //优先从缓存中读取字典配置
          if (getDictItemsFromCache(this.dictCode)) {
            this.options = getDictItemsFromCache(this.dictCode)
            return
          }
          this.loading = true
          ajaxGetDictItems(this.dictCode, null).then((res) => {
            this.loading = false
            if (res.success) {
              this.options = res.result
            } else {
              this.$message.warning(res.message)
            }
          })
        } else if (this.dict && value) {
          this.loading = true
          // 字典code格式：table,text,code
          getAction(`/sys/dict/loadDict/${this.dict}`, { keyword: value, pageSize: this.pageSize }).then((res) => {
            this.loading = false
            if (res.success) {
              this.options = res.result
            } else {
              this.$message.warning(res.message)
            }
          })
        }
      }
    },
    // 搜索过滤器
    filterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },
    // 搜索动作
    handleSearch: simpleDebounce(function (value) {
      if (this.dict) {
        this.loadOptions(value)
      }
    }, 400),
    //选中动作
    handleChange(selectedValue) {
      if (this.multiple) {
        if (selectedValue.length === 0) {
          this.$emit('input', undefined)
        } else {
          this.$emit('input', selectedValue.length > 1 ? selectedValue.join(',') : selectedValue[0])
        }
      } else {
        this.$emit('input', selectedValue)
      }
    },
  },
}
</script>
